/**
 * 主渲染程序
 * by ZL 2018/11/27 重构
 */
import zrender from "zrender";
import config from "./config";
import ajax from "./ajax";
import utils from "./utils";
import tools from "./tools";
import plugin from "./plug-in";
export default {
  zoomIn: false,
  picId: null,
  htmlDom: null,
  picXML: null,
  canvas: null,
  root: null,
  rootRect: null,
  dtextRect: null,
  lastTimeout: null,
  cacheElement: [],
  cachePicId: [],
  initRender(dom, id) {
    this.picId = id;
    this.htmlDom = dom;
    this.getRenderXml();
  },
  disposeRender() {
    if (this.canvas) {
      this.canvas.off("mouseup");
      this.canvas.off("mousemove");
      this.canvas.off("mousewheel");
      this.canvas.dispose();
    }
    this.canvas = null;
    this.zoomIn = false;
    this.cacheElement = [];

    if (this.lastTimeout) {
      clearTimeout(this.lastTimeout);
    }
    // 销毁plugin中的时钟定时器
    plugin.disposeTimer();
    // 取消请求
    ajax.metaSources.forEach(source => {
      source();
    });
    ajax.metaSources.length = 0;
  },
  resizeRender() {
    if (this.canvas && this.canvas.painter) {
      this.canvas.resize();
      // 重新计算缩放 start
      const xmlDoc = this.picXML.documentElement;
      const rootWidth = utils.getAttribute(xmlDoc, "w", "int");
      const rootHeight = utils.getAttribute(xmlDoc, "h", "int");
      const canvasWidth = this.canvas.getWidth();
      const canvasHeight = this.canvas.getHeight();
      const sc =
        canvasHeight / rootHeight > canvasWidth / rootWidth
          ? canvasWidth / rootWidth
          : canvasHeight / rootHeight;
      const dx = canvasWidth / 2 - rootWidth / 2;
      const dy = canvasHeight / 2 - rootHeight / 2;
      this.root.attr({
        position: [dx, dy],
        scale: [sc, sc],
        origin: [rootWidth / 2, rootHeight / 2],
      });
      // 重新计算缩放 end
    }
  },
  async getRenderXml() {
    this.disposeRender(); // 这里清除上一次渲染结果 2018/10/9
    this.picXML = (await ajax.GetPicGXml(this.picId)).data;
    if (this.picXML) {
      this.createCanvas();
    }
  },
  createCanvas() {
    this.canvas = zrender.init(this.htmlDom, { renderer: config.renderer });
    this.createRoot();
  },
  createRoot() {
    const xmlDoc = this.picXML.documentElement;
    const rootWidth = utils.getAttribute(xmlDoc, "w", "int");
    const rootHeight = utils.getAttribute(xmlDoc, "h", "int");
    const canvasWidth = this.canvas.getWidth();
    const canvasHeight = this.canvas.getHeight();
    // 初始化缩放和位置计算
    const sc =
      canvasHeight / rootHeight > canvasWidth / rootWidth
        ? canvasWidth / rootWidth
        : canvasHeight / rootHeight;
    const dx = canvasWidth / 2 - rootWidth / 2;
    const dy = canvasHeight / 2 - rootHeight / 2;
    this.root = new zrender.Group({
      position: [dx, dy],
      scale: [sc, sc],
      origin: [rootWidth / 2, rootHeight / 2],
    });
    this.rootRect = new zrender.Rect({
      cursor: config.cursors.move,
      shape: {
        x: 0,
        y: 0,
        width: rootWidth,
        height: rootHeight,
      },
      style: {
        fill: utils.getAttribute(xmlDoc, "bgc", "rgb"),
      },
    });
    // 添加一个DText选择框
    this.dtextRect = new zrender.Rect({
      style: {
        stroke: "#fff",
        lineDash: [5, 3],
        lineWidth: 1,
        strokeNoScale: true,
      },
    });
    // 添加刷新时间
    // const refreshTime = new zrender.Text({
    //   style: {
    //     color: "#000",
    //     text: "2023年12月6日 09:00:00",
    //     fontSize: "23",
    //   },
    //   position: [rootWidth - 500, 30],
    // });
    this.root.add(this.rootRect);
    this.root.add(this.dtextRect);
    // this.root.add(refreshTime);
    this.canvas.add(this.root);

    // 处理ie兼容性问题 2018/5/22
    if (typeof xmlDoc.children === "undefined") {
      this.getXMLChildren(xmlDoc);
    }

    if (xmlDoc.children && xmlDoc.children.length) {
      for (let i = 0; i < xmlDoc.children.length; i++) {
        this.renderElement(this.root, xmlDoc.children[i]);
      }
    }
    // 加载事件
    this.loadEventful();
    // 加载数据
    if (this.cacheElement.length) {
      this.loadRenderData();
    }
  },
  // 处理ie兼容性问题 2018/5/22
  getXMLChildren(xmlDoc) {
    xmlDoc.children = [];
    const nodes = xmlDoc.childNodes;
    for (let i = 0; i < nodes.length; i++) {
      if (nodes[i].nodeType === 1) {
        xmlDoc.children.push(nodes[i]);
        this.getXMLChildren(nodes[i]);
      }
    }
  },
  // 元素渲染开始
  renderElement(parent, xmlNode) {
    const nodeName = xmlNode.nodeName;
    let element = null;
    switch (nodeName) {
      case "Layer":
        element = tools.renderLayer(xmlNode);
        break;
      case "line":
        element = tools.renderLine(xmlNode);
        break;
      case "Bus":
        element = tools.renderBus(xmlNode);
        break;
      case "ConnectLine":
        element = tools.renderConnectLine(xmlNode);
        break;
      case "text":
        element = tools.renderText(xmlNode);
        break;
      case "rect":
      case "roundrect":
        element = tools.renderRect(xmlNode);
        break;
      case "polyline":
        element = tools.renderPolyline(xmlNode);
        break;
      case "LinkArea":
        element = tools.renderLinkArea(xmlNode);
        break;
      case "Status":
        element = tools.renderStatus(xmlNode);
        break;
      case "circle":
      case "Pin":
        element = tools.renderCircle(xmlNode);
        break;
      case "ellipse":
        element = tools.renderEllipse(xmlNode);
        break;
      case "polygon":
        element = tools.renderPolygon(xmlNode);
        break;
      case "image":
        // 判断图层还是元件，取不同图片路径
        if (parent.layer) {
          element = tools.renderImage(xmlNode, config.pic_g_url);
        } else {
          element = tools.renderImage(xmlNode, config.meta_g_url);
        }
        break;
      case "ellipsearc":
        element = tools.renderEllipseArc(xmlNode);
        break;
      case "DText":
        element = tools.renderDText(xmlNode);
        break;
      // 渲染插件
      case "Clock":
        element = plugin.plugClock(xmlNode);
        break;
      default:
      // 元素未定义
    }
    if (element) {
      // 增加一个状态属性
      const sta = utils.getAttribute(xmlNode, "sta");
      if (sta) {
        element.attr("sta", sta);
      }
      parent.add(element);
    }
  },
  // 加载事件
  loadEventful() {
    const mouseState = {
      down: false,
      x: 0,
      y: 0,
      dx: 0,
      dy: 0,
    };
    // root 初始状态
    const rootPosition = [this.root.position[0], this.root.position[1]];
    const rootState = {
      position: [this.root.position[0], this.root.position[1]],
      scale: [this.root.scale[0], this.root.scale[1]],
    };
    this.canvas.on("mousedown", e => {
      mouseState.down = true;
      mouseState.x = e.offsetX;
      mouseState.y = e.offsetY;
      rootState.position = this.root.position;

      this.rootRect.attr({
        cursor: config.cursors.moving,
      });
    });
    this.canvas.on("mouseup", e => {
      mouseState.down = false;
      this.rootRect.attr({
        cursor: config.cursors.move,
      });
    });
    this.canvas.on("mousemove", e => {
      // && this.zoomIn
      if (mouseState.down) {
        this.rootRect.attr({
          cursor: config.cursors.moving,
        });
        const moveX = e.offsetX - mouseState.x;
        const moveY = e.offsetY - mouseState.y;
        const movePosition = [
          rootState.position[0] + moveX,
          rootState.position[1] + moveY,
        ];
        this.root.attr({
          position: movePosition,
        });
        mouseState.x = e.offsetX;
        mouseState.y = e.offsetY;
        // 总移动的距离
        mouseState.dx = mouseState.dx + moveX;
        mouseState.dy = mouseState.dy + moveY;
      }
    });
    this.canvas.on("mousewheel", e => {
      const sc = this.root.scale;
      if (e.wheelDelta > 0) {
        this.root.attr({
          scale: [sc[0] / 0.8, sc[1] / 0.8],
        });
      }
      if (e.wheelDelta < 0 && this.zoomIn) {
        this.root.attr({
          scale: [sc[0] * 0.8, sc[1] * 0.8],
        });
      }
      if (e.wheelDelta < 0 && this.root.position[0] !== rootPosition[0]) {
        this.root.attr({
          position: [
            this.root.position[0] - mouseState.dx,
            this.root.position[1] - mouseState.dy,
          ],
        });
      }
      // 初始状态下不能缩小，与cs端一致
      if (this.root.scale[0] > rootState.scale[0]) {
        this.zoomIn = true;
      } else {
        this.zoomIn = false;
        mouseState.dx = 0;
        mouseState.dy = 0;
        // 快速缩小时可视范围丢失图bug 2019/10/9
        this.root.attr({
          position: rootPosition,
        });
      }
    });
  },
  async loadRenderData() {
    let strOidAttrs = "";
    this.cacheElement.forEach((entry, index) => {
      if (index === 0) {
        strOidAttrs = entry.keyid + "," + entry.attrid;
      } else {
        strOidAttrs += ";" + entry.keyid + "," + entry.attrid;
      }
    });

    const res = await ajax.GetRenderData({
      XRtOidAttrs: strOidAttrs,
    });
    const rtdata = res.data.info;

    // 这里处理一个bug，防止picId切换的时请求未结束
    if (rtdata.length === this.cacheElement.length) {
      for (let i = 0; i < rtdata.length; i++) {
        const updateEle = this.cacheElement[i];
        if (updateEle && updateEle.type === "DText") {
          // 这里增加了遥测图元属性 2018/10/9 by ZL
          let sign = "--.--";
          let text = rtdata[i].columnValue;
          if (updateEle.extra[0] && updateEle.extra[1] !== null) {
            for (let i = 0; i < updateEle.extra[0]; i++) {
              if (i === 0) sign = "-";
              else if (i === updateEle.extra[0] - updateEle.extra[1] - 1)
                sign += "-.";
              else sign += "-";
            }
            text = text ? parseFloat(text).toFixed(updateEle.extra[1]) : "";
          }
          if (updateEle.extra[2] && text) text = updateEle.extra[2] + text;
          if (updateEle.extra[3] && text) text = text + updateEle.extra[3];
          updateEle.element.attr({
            style: {
              text: parseFloat(text).toFixed(2) || sign,
            },
          });
        } else {
          updateEle &&
            this.refreshStatus(updateEle.element, rtdata[i].columnValue || "0");
          // 处理动画效果
          if (updateEle && updateEle.animate) {
            if (updateEle.metaId === "1298") {
              if (rtdata[i].columnValue && rtdata[i].columnValue === "0") {
                updateEle.animate.start();
              } else {
                updateEle.animate.stop();
              }
            } else {
              if (rtdata[i].columnValue && rtdata[i].columnValue === "1") {
                updateEle.animate.start();
              } else {
                updateEle.animate.stop();
              }
            }
          }
        }
      }
      // 先清理
      if (this.lastTimeout) {
        clearTimeout(this.lastTimeout);
      }
      // 轮询请求
      this.lastTimeout = setTimeout(() => {
        this.loadRenderData();
      }, config.intervalTime);
    }
  },
  refreshStatus(statusEle, state) {
    statusEle.eachChild(ele => {
      if (ele.isGroup) {
        this.refreshStatus(ele, state);
      } else {
        if (ele.sta && ele.sta !== state) {
          ele.hide();
        } else {
          ele.show();
        }
      }
    });
  },
};
